<?php

class LARQSParql extends GenericSparql {

  /**
   * Query for concepts using a search term. Use the LARQ Lucene index when possible.
   * @param string $term search term
   * @param string $lang language code
   * @param int $limit maximum number of hits to retrieve; 0 for unlimited
   * @param int $offset offset of results to retrieve; 0 for beginning of list
   * @return EasyRDF_Sparql_Result query result object
   */
  public function queryConcepts($term, $lang, $limit, $offset) {
    $gc = $this->graphClause;
    $gr = $this->graph[0] == '?' ? $this->graph : '';
    $limit = ($limit) ? 'LIMIT ' . $limit : '';
    $offset = ($offset) ? 'OFFSET ' . $offset : '';

    // extra conditions for label language, if specified
    $labelcond = ($lang) ? "&& langMatches(lang(?match), '$lang')" : "";

    $orderextra = ($this->graph[0] == '?') ? $this->graph : '';

    $textmatch = "";
    if ($term == '0-9') {
      $term = '[0-9]';
    } elseif ($term == '!*') {
      $term = '[^A-Za-zåÅöÖäÄ0-9]';
    } elseif (strpos($term, '*') !== false || strpos($term, ' ') !== false) {
      while ($term[strlen($term) - 1] == '*' || $term[strlen($term) - 1] == ' ') {  // removes asterisks from the end of the search term
        $term = substr($term, 0, strlen($term) - 1);
        if (strlen($term) == 0)
          break;
      }
      while (strpos($term, '**') !== false)
        $term = str_replace('**', '*', $term); // removes futile asterisks
      $term = str_replace('*', '.*', $term); // just to fix regex-syntax to work as expected
    } elseif (preg_match('/^\p{L}[\p{L} _.-]+$/u', $term) == 1) { // check that the query is unproblematic for Lucene
      # optimize query by adding textMatch clauses, using LARQ index
      $textmatch = "{ SELECT ?match
                      WHERE { 
                        ?match pf:textMatch '+$term*' .
                        FILTER (regex(?match, '^$term.*', 'i') $labelcond)
                      }
                    }";            
    }

    $query = <<<EOQ
      SELECT DISTINCT ?s ?label ?alabel $gr WHERE {
       $textmatch
       $gc {
        {
         ?s skos:prefLabel ?match .
         BIND (?match as ?label)
         ?s rdf:type skos:Concept .
         FILTER (regex(?match, "^$term.*", "i")
                 $labelcond)
        }
        UNION
        {
         ?s skos:altLabel ?match .
         BIND (?match as ?alabel)
         ?s rdf:type skos:Concept .
         ?s skos:prefLabel ?label .
         FILTER (regex(?match, "^$term.*", "i")
                 && !regex(?label, "^$term.*", "i")
                 && langMatches(lang(?match), lang(?label))
                 $labelcond
                )
        }
       }

      } ORDER BY lcase(?match) $orderextra
      $limit
      $offset
EOQ;
    return $this->client->query($query);
  }
}

?>
